package com.vichat.business.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.vichat.business.entity.DistrictFence;
import com.vichat.business.entity.DistrictFenceRule;
import com.vichat.business.entity.DistrictFenceUser;
import com.vichat.business.entity.VcAlarm;
import com.vichat.business.service.IDistrictFenceService;
import com.vichat.business.service.IVcAlarmService;
import com.vichat.business.vo.FenceVO;
import com.vichat.common.cache.RedisHelper;
import com.vichat.common.constant.I18nConstant;
import com.vichat.common.exception.ViChatException;
import com.vichat.common.util.DateUtil;
import com.vichat.common.util.I18NUtil;
import com.vichat.common.util.NumberUtils;
import com.vichat.common.util.StringUtil;
import com.vichat.common.vo.Json;
import com.vichat.common.vo.PageFilter;
import com.vichat.core.dao.BaseDaoI;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

@Service("districtFenceService")
public class DistrictFenceServiceImpl implements IDistrictFenceService {

    @Autowired
    private BaseDaoI<DistrictFence> districtFenceDao;
    @Autowired
    private BaseDaoI<DistrictFenceRule> districtFenceRuleDao;
    @Autowired
    private BaseDaoI<DistrictFenceUser> districtFenceUserDao;


    @Override
    public DistrictFence getDistrictFenceByfenceId(long fenceId) {
        String hql = "from DistrictFence where state = 1 and fenceId = :fenceId";
        HashMap params = new HashMap();
        params.put("fenceId", fenceId);
        List<DistrictFence> districtFences = districtFenceDao.find(hql, params);
        if (districtFences != null && !districtFences.isEmpty()) {
            return districtFences.get(0);
        }
        return null;
    }

    @Override
    public DistrictFenceUser getDistrictFenceUserById(long id, long fenceId) {
        String hql = "from DistrictFenceUser where state = 1 and fenceId = :fenceId and userId = :userId";
        HashMap params = new HashMap();
        params.put("fenceId", fenceId);
        params.put("userId", id);
        List<DistrictFenceUser> fenceUsers = districtFenceUserDao.find(hql, params);
        if (fenceUsers != null && !fenceUsers.isEmpty()) {
            return fenceUsers.get(0);
        }
        return null;
    }

    public List<DistrictFenceUser> getDistrictFenceUserByfenceId(long fenceId) {
        String hql = "from DistrictFenceUser where state = 1 and fenceId = :fenceId";
        HashMap params = new HashMap();
        params.put("fenceId", fenceId);
        List<DistrictFenceUser> districtFences = districtFenceUserDao.find(hql, params);
        return districtFences;
    }

    public DistrictFenceRule getDistrictFenceRuleByfenceId(long fenceId) {
        String hql = "from DistrictFenceRule where state = 1 and fenceId = :fenceId";
        HashMap params = new HashMap();
        params.put("fenceId", fenceId);
        List<DistrictFenceRule> districtFences = districtFenceRuleDao.find(hql, params);
        if (districtFences != null && !districtFences.isEmpty()) {
            return districtFences.get(0);
        }
        return null;
    }

    public DistrictFenceRule getDistrictFenceRuleByRuleId(long ruleId) {
        String hql = "from DistrictFenceRule where state = 1 and ruleId = :ruleId";
        HashMap params = new HashMap();
        params.put("ruleId", ruleId);
        List<DistrictFenceRule> districtFences = districtFenceRuleDao.find(hql, params);
        if (districtFences != null && !districtFences.isEmpty()) {
            return districtFences.get(0);
        }
        return null;
    }

    public DistrictFenceUser getDistrictFenceUser(long id, long fenceId, long type) {
        String hql = "from DistrictFenceUser where fenceId = :fenceId and userId = :userId and type = :type";
        HashMap params = new HashMap();
        params.put("fenceId", fenceId);
        params.put("userId", id);
        params.put("type", type);
        List<DistrictFenceUser> districtFences = districtFenceUserDao.find(hql, params);
        if (districtFences != null && !districtFences.isEmpty()) {
            return districtFences.get(0);
        }
        return null;
    }

    public DistrictFence queryDistrictFenceByfenceId(long partyId, long fenceId) {
        String json = RedisHelper.getDistrictFence(partyId, fenceId);
        DistrictFence districtFence = null;

        if (StringUtils.isNotBlank(json)) {
            FenceVO fenceVO = JSONObject.parseObject(json, FenceVO.class);
            districtFence = fenceVO.getDistrictFence();
        } else {
            districtFence = getDistrictFenceByfenceId(fenceId);
            FenceVO fenceVO = new FenceVO();
            fenceVO.setDistrictFence(districtFence);
            RedisHelper.putDistrictFence(partyId,fenceId,JSONArray.toJSONString(fenceVO));
        }
        return districtFence;
    }

    @Override
    public void saveFence(FenceVO fenceVO) throws ViChatException {
        DistrictFence districtFence = fenceVO.getDistrictFence();//电子围栏
        districtFenceDao.save(districtFence);
        if (fenceVO.getDistrictFenceUser() != null && !fenceVO.getDistrictFenceUser().isEmpty()) {//电子围栏 监控用户和通知用户
            for (DistrictFenceUser fenceUser : fenceVO.getDistrictFenceUser()) {
                DistrictFenceUser districtFenceUser = new DistrictFenceUser();
                districtFenceUser.setFenceId(districtFence.getFenceId());
                districtFenceUser.setUserId(fenceUser.getUserId());
                districtFenceUser.setType(fenceUser.getType());
                districtFenceUserDao.save(districtFenceUser);

                RedisHelper.putUserDistrictFence(fenceUser.getUserId(),districtFence.getFenceId());
            }
        }
        fenceVO.getDistrictFenceRule().setFenceId(districtFence.getFenceId());
        districtFenceRuleDao.save(fenceVO.getDistrictFenceRule()); //电子围栏 规则
        RedisHelper.putDistrictFence(districtFence.getPartyId(), districtFence.fenceId, JSONArray.toJSONString(fenceVO));
    }

    @Override
    public void saveDistrictFence(DistrictFence districtFence) throws ViChatException {
        DistrictFence districtFenceFDB = districtFenceDao.get(DistrictFence.class, districtFence.getFenceId());
        districtFenceFDB.setFenceDesc(districtFence.getFenceDesc());
        districtFenceFDB.setFenceName(districtFence.getFenceName());
        districtFenceFDB.setFenceType(districtFence.getFenceType());
        districtFenceFDB.setRegcoords(districtFence.getRegcoords());
        districtFenceDao.save(districtFenceFDB); //电子围栏
        String fenceVOJSONStr = RedisHelper.getDistrictFence(districtFence.getPartyId(), districtFence.fenceId);
        FenceVO fenceVO = JSONObject.parseObject(fenceVOJSONStr, FenceVO.class);
        fenceVO.setDistrictFence(districtFenceFDB);
        RedisHelper.putDistrictFence(districtFence.getPartyId(), districtFence.fenceId, JSONArray.toJSONString(fenceVO));
    }

    @Override
    public void saveDistrictFenceUser(long partyId, DistrictFenceUser queryBean) {
        deleteFenceUserByFenceId(queryBean.getFenceId(), queryBean.getType());
        for (long uid : queryBean.getIds()) {
            DistrictFenceUser districtFenceUser = new DistrictFenceUser();
            districtFenceUser.setFenceId(queryBean.getFenceId());
            districtFenceUser.setUserId(uid);
            districtFenceUser.setType(queryBean.getType());
            districtFenceUserDao.save(districtFenceUser);

            RedisHelper.putUserDistrictFence(districtFenceUser.getUserId(),queryBean.getFenceId());
        }
        updateFenceUserRedis(partyId, queryBean.getFenceId());
    }

    @Override
    public DistrictFenceRule saveDistrictFenceRule(long partyId, DistrictFenceRule queryBean) throws ViChatException {
        if (NumberUtils.isNotNullOrZero(queryBean.getRuleId())) {
            DistrictFenceRule districtFenceRule = this.getDistrictFenceRuleByRuleId(queryBean.getRuleId());
            if (districtFenceRule == null) {
                String errorMsg = I18NUtil.getMessage("error_fenceNotExist", null, Locale.CHINA);
                throw new ViChatException(I18nConstant.error_fenceNotExist, errorMsg);
            }
            districtFenceRule.setRuleType(queryBean.getRuleType());
            districtFenceRule.setRuleJson(queryBean.getRuleJson());
            districtFenceRule.setRuleCondition(queryBean.getRuleCondition());
            districtFenceRule.setAlarmLevel(queryBean.getAlarmLevel());
            districtFenceRuleDao.update(districtFenceRule);
        } else {
            queryBean.setState(1L);
            districtFenceRuleDao.save(queryBean);
        }

        updateFenceRuleRedis(partyId, queryBean.getFenceId());
        return queryBean;
    }

    @Override
    public List<DistrictFence> queryDistrictFences(DistrictFence queryBean, PageFilter pf) {
        String hql = "from DistrictFence where state = 1";
        HashMap params = new HashMap();
        return districtFenceDao.find(hql + queryDistrictFenceWhereHql(queryBean, params) + " order by fenceId", params, pf.getPage(), pf.getRows());
    }

    @Override
    public Long countDistrictFences(DistrictFence queryBean) {
        String hql = "select count(*) from DistrictFence where state = 1";
        HashMap params = new HashMap();
        return districtFenceDao.count(hql + queryDistrictFenceWhereHql(queryBean, params), params);
    }

    private String queryDistrictFenceWhereHql(DistrictFence queryBean, HashMap params) {
        String hql = "";
        if (NumberUtils.isNotNullOrZero(queryBean.getFenceType())) {
            hql += " and fenceType = :fenceType";
            params.put("fenceType", queryBean.getFenceType());
        }
        if (NumberUtils.isNotNullOrZero(queryBean.getPartyId())) {
            hql += " and partyId = :partyId";
            params.put("partyId", queryBean.getPartyId());
        }
        if (StringUtils.isNotBlank(queryBean.getFenceName())) {
            hql += " and fenceName like :fenceName or fenceDesc like :fenceName";
            params.put("fenceName", "%" + queryBean.getFenceType() + "%");
        }
        return hql;
    }

    @Override
    public List<DistrictFenceRule> queryDistrictFenceRules(DistrictFenceRule queryBean, PageFilter pf) {
        String hql = "from DistrictFenceRule where state = 1";
        HashMap params = new HashMap();
        return districtFenceRuleDao.find(hql + queryDistrictFenceRuleWhereHql(queryBean, params), params, pf.getPage(), pf.getRows());
    }

    @Override
    public Long countDistrictFenceRules(DistrictFenceRule queryBean) {
        String hql = "select count(*) from DistrictFenceRule where state = 1";
        HashMap params = new HashMap();
        return districtFenceRuleDao.count(hql + queryDistrictFenceRuleWhereHql(queryBean, params), params);
    }

    private String queryDistrictFenceRuleWhereHql(DistrictFenceRule queryBean, HashMap params) {
        String hql = "";
        if (NumberUtils.isNotNullOrZero(queryBean.getFenceId())) {
            hql += " and fenceId = :fenceId";
            params.put("fenceId", queryBean.getFenceId());
        }
        if (NumberUtils.isNotNullOrZero(queryBean.getRuleType())) {
            hql += " and ruleType = :ruleType";
            params.put("ruleType", queryBean.getRuleType());
        }
        if (NumberUtils.isNotNullOrZero(queryBean.getRuleCondition())) {
            hql += " and ruleCondition = :ruleCondition";
            params.put("ruleCondition", queryBean.getRuleCondition());
        }
        if (StringUtils.isNotBlank(queryBean.getRuleJson())) {
            hql += " and ruleType like :ruleType";
            params.put("ruleType", "%" + queryBean.getRuleJson() + "%");
        }
        return hql;
    }


    @Override
    public List<DistrictFenceUser> queryDistrictFenceUsers(DistrictFenceUser queryBean, PageFilter pf) {
        String hql = "from DistrictFenceUser where state = 1";
        HashMap params = new HashMap();
        return districtFenceUserDao.find(hql + queryDistrictFenceUserWhereHql(queryBean, params), params, pf.getPage(), pf.getRows());
    }

    @Override
    public Long countDistrictFenceUsers(DistrictFenceUser queryBean) {
        String hql = "select count(*) from DistrictFenceUser where state = 1";
        HashMap params = new HashMap();
        return districtFenceUserDao.count(hql + queryDistrictFenceUserWhereHql(queryBean, params), params);
    }

    private String queryDistrictFenceUserWhereHql(DistrictFenceUser queryBean, HashMap params) {
        String hql = "";
        if (NumberUtils.isNotNullOrZero(queryBean.getFenceId())) {
            hql += " and fenceId = :fenceId";
            params.put("fenceId", queryBean.getFenceId());
        }
        if (NumberUtils.isNotNullOrZero(queryBean.getUserId())) {
            hql += " and userId = :userId";
            params.put("userId", queryBean.getUserId());
        }
        if (NumberUtils.isNotNullOrZero(queryBean.getType())) {
            hql += " and 'type' = :type";
            params.put("type", queryBean.getType());
        }
        return hql;
    }

    public void deleteFence(long fenceId) throws ViChatException {
        DistrictFence fenceFDB = getDistrictFenceByfenceId(fenceId);
        if (fenceFDB == null) {
            String errorMsg = I18NUtil.getMessage("error_fenceNotExist", null, Locale.CHINA);
            throw new ViChatException(I18nConstant.error_fenceNotExist, errorMsg);
        }

        fenceFDB.setState(0L);
        districtFenceDao.update(fenceFDB);

        deleteFenceUserByFenceId(fenceId);
        deleteFenceRuleByFenceId(fenceId);
        RedisHelper.delDistrictFence(fenceFDB.getPartyId(), fenceId);
    }

    @Override
    public void deleteFenceUser(long partyId, long fenceId, long id, long type) throws ViChatException {
        DistrictFenceUser fenceUserFDB = getDistrictFenceUser(id, fenceId, type);
        if (fenceUserFDB == null) {
            String errorMsg = I18NUtil.getMessage("error_fenceUserNotExist", null, Locale.CHINA);
            throw new ViChatException(I18nConstant.error_fenceUserNotExist, errorMsg);
        }

        districtFenceUserDao.delete(fenceUserFDB);

        RedisHelper.delUserDistrictFence(fenceUserFDB.getUserId(),fenceId);

    }

    public void deleteFenceUserByFenceId(long fenceId) throws ViChatException {
        List<DistrictFenceUser> fenceUserList = getDistrictFenceUserByfenceId(fenceId);
        if (fenceUserList == null) {
            throw new ViChatException(I18nConstant.error_fenceUserNotExist, "");
        }
        for (DistrictFenceUser fenceUser : fenceUserList) {
            districtFenceUserDao.delete(fenceUser);
            RedisHelper.delUserDistrictFence(fenceUser.getUserId(),fenceId);
            RedisHelper.delFenceAlarmTime(fenceUser.getUserId(), fenceUser.getFenceId());
        }
    }

    @Override
    public void deleteFenceRule(long partyId, long ruleId) throws ViChatException {
        DistrictFenceRule ruleFDB = getDistrictFenceRuleByRuleId(ruleId);
        if (ruleFDB == null) {
            String errorMsg = I18NUtil.getMessage("error_fenceRuleNotExist", null, Locale.CHINA);
            throw new ViChatException(I18nConstant.error_fenceRuleNotExist, errorMsg);
        }

        ruleFDB.setState(0L);
        districtFenceRuleDao.update(ruleFDB);

        updateFenceRuleRedis(partyId, ruleFDB.getFenceId());
    }

    public void deleteFenceRuleByFenceId(long fenceId) throws ViChatException {
        DistrictFenceRule fenceRule = getDistrictFenceRuleByfenceId(fenceId);
        if (fenceRule == null) {
            throw new ViChatException(I18nConstant.error_fenceRuleNotExist, "");
        }
        fenceRule.setState(0L);
        districtFenceRuleDao.update(fenceRule);
    }


    public void updateFenceUserRedis(long partyId, long fenceId) {
        List<DistrictFenceUser> userList = this.getDistrictFenceUserByfenceId(fenceId);

        String fenceVOJSONStr = RedisHelper.getDistrictFence(partyId, fenceId);
        FenceVO fenceVO = JSONObject.parseObject(fenceVOJSONStr, FenceVO.class);
        if (fenceVO != null) {
            fenceVO.setDistrictFenceUser(userList);
            RedisHelper.putDistrictFence(partyId, fenceId, JSONArray.toJSONString(fenceVO));
        }
    }

    public void updateFenceRuleRedis(long partyId, long fenceId) {
        DistrictFenceRule rule = this.getDistrictFenceRuleByfenceId(fenceId);

        String fenceVOJSONStr = RedisHelper.getDistrictFence(partyId, fenceId);
        FenceVO fenceVO = JSONObject.parseObject(fenceVOJSONStr, FenceVO.class);
        if (fenceVO != null) {
            fenceVO.setDistrictFenceRule(rule);
            RedisHelper.putDistrictFence(partyId, fenceId, JSONArray.toJSONString(fenceVO));
        }
    }

    public void deleteFenceUserByFenceId(long fenceId, long type) {
        String sql = "delete from businessdb.district_fence_user where fence_id=:fenceId and type = :type";
        HashMap params = new HashMap();
        params.put("fenceId", fenceId);
        params.put("type", type);
        districtFenceUserDao.executeSql(sql, params);
    }

}
